//headfile of Page Tbl analization
#include "length.h"
#include "MC.h"
#include "BasicMatic.h"
extern volatile _mch kmemory;

#define PAGE_SIZE  (1 << 12)
#define PAGE_SIZE_OFFSET (12)
constexpr _ptlong _PTLONG_OFFSET(){return sizeof(_ptlong) * 8;}
constexpr _ptlong _LOWB(_ptlong x) {return ((~0) >> (sizeof(_ptlong) * 8 - x));}

constexpr _ptlong _PageNum(_ptlong first_offset,_ptlong second_offset)
{
  return ( ((1 << (first_offset - second_offset)) * sizeof(_ptlong)) % PAGE_SIZE == 0
	   ? ((1 << (first_offset - second_offset)) * sizeof(_ptlong)) / PAGE_SIZE
	   : ((1 << (first_offset - second_offset)) * sizeof(_ptlong)) / PAGE_SIZE + 1);
	   
}

#define PageTblApply(x,y)  PageApply(x,y)

template<int... argv>
struct __PageTbl{};

template<int layer = 0,int foffset,int soffset, int... argv>
struct __PageTbl
{
  static inline _ptlong* PageTblInit()
  {//PageTbl need Align
    return PageTblApply(_PageNum(sizeof(_ptlong)* 8 ,foffset),&kmemory);
  }

  static inline _ptlong* PDAddr(_ptlong tblAddr,_ptlong vMem)  //PageDiscriptionAddress
  {
    _ptlong* ntblAddr = ((_ptlong*)((tblAddr & (~_LOWB(foffset))) + (vMem >> foffset) * sizeof(_ptlong)));
    if(*ntblAddr == 0)
      {
	_ptlong size;
	*ntblAddr = PageTblApply(size = _PageNum(foffset - soffset),&kmemory);
	_MemAll(0,ntblAddr,size << PAGE_SIZE_OFFSET);
      }
    return PageTbl<layer + 1,soffset,argv...>::PDAddr(*ntblAddr, vMem & _LOWB(foffset));
  }
};

template<int layer,int offset>
struct __PageTbl
{
  static inline _ptlong* PageTblInit()
  {//PageTbl need Align
    return PageTblApply(_PageNum(sizeof(_ptlong)* 8 ,offset),&kmemory);
  }

  static inline _ptlong* PDAddr(_ptlong tblAddr,_ptlong vMem)
  {
    return (_ptlong*)(tblAddr + (vMem >> offset) * sizeof(_ptlong));
  }
};
